<?php

class FileUpload {

    private $filepath;     //指定上传文件保存的路径
    private $allowtype = array('gif', 'jpg', 'png', 'jpeg');  //充许上传文件的类型
    private $maxsize = 1000000;  //允上传文件的最大长度 1M
    private $israndname = true;  //是否随机重命名， true false不随机，使用原文件名
    private $originName;   //源文件名称
    private $tmpFileName;   //临时文件名
    private $fileType;  //文件类型
    private $fileSize;  //文件大小
    private $newFileName; //新文件名
    private $errorNum = 0;  //错误号
    private $errorMess = ""; //用来提供错误报告

//用于对上传文件初使化
//1. 指定上传路径， 2，充许的类型， 3，限制大小， 4，是否使用随机文件名称
//让用户可以不用按位置传参数，后面参数给值不用将前几个参数也提供值

    function __construct($options = array()) {
        foreach ($options as $key => $val) {
            $key = strtolower($key);
//查看用户参数中数组的下标是否和成员属性名相同
            if (!in_array($key, get_class_vars(get_class($this)))) {
                continue;
            }

            $this->setOption($key, $val);
        }
    }

    private function getError() {
        $str = "上传文件<font color='red'>{$this->originName}</font>时出错：";

        switch ($this->errorNum) {
            case 4: $str .= "没有文件被上传";
                break;
            case 3: $str .= "文件只被部分上传";
                break;
            case 2: $str .= "上传文件超过了HTML表单中MAX_FILE_SIZE选项指定的值";
                break;
            case 1: $str .= "上传文件超过了php.ini 中upload_max_filesize选项的值";
                break;
            case -1: $str .= "末充许的类型";
                break;
            case -2: $str .= "文件过大，上传文件不能超过{$this->maxSize}个字节";
                break;
            case -3: $str .= "上传失败";
                break;
            case -4: $str .= "建立存放上传文件目录失败，请重新指定上传目录";
                break;
            case -5: $str .= "必须指定上传文件的路径";
                break;

            default: $str .= "末知错误";
        }

        return $str . '<br>';
    }

//用来检查文件上传路径
    private function checkFilePath() {
        if (empty($this->filepath)) {
            $this->setOption('errorNum', -5);
            return false;
        }

        if (!file_exists($this->filepath) || !is_writable($this->filepath)) {
            if (!@mkdir($this->filepath, 0755)) {
                $this->setOption('errorNum', -4);
                return false;
            }
        }
        return true;
    }

//用来检查文件上传的大小
    private function checkFileSize() {
        if ($this->fileSize > $this->maxsize) {
            $this->setOPtion('errorNum', '-2');
            return false;
        } else {
            return true;
        }
    }

//用于检查文件上传类型
    private function checkFileType() {
        if (in_array(strtolower($this->fileType), $this->allowtype)) {
            return true;
        } else {
            $this->setOption('errorNum', -1);
            return false;
        }
    }

//设置上传后的文件名称
    private function setNewFileName() {
        if ($this->israndname) {
            $this->setOption('newFileName', $this->proRandName());
        } else {
            $this->setOption('newFileName', $this->originName);
        }
    }

//设置随机文件名称
    private function proRandName() {
        $fileName = date("YmdHis") . rand(100, 999);
        return $fileName . '.' . $this->fileType;
    }

    private function setOption($key, $val) {
        $this->$key = $val;
    }

//用来上传一个文件
    function uploadFile($fileField) {
        $return = true;
//检查文件上传路径
        if (!$this->checkFilePath()) {
            $this->errorMess = $this->getError();
            return false;
        }

        $name = $_FILES[$fileField]['name'];
        $tmp_name = $_FILES[$fileField]['tmp_name'];
        $size = $_FILES[$fileField]['size'];
        $error = $_FILES[$fileField]['error'];

        if (is_Array($name)) {
            $errors = array();

            for ($i = 0; $i < count($name); $i++) {
                if ($this->setFiles($name[$i], $tmp_name[$i], $size[$i], $error[$i])) {
                    if (!$this->checkFileSize() || !$this->checkFileType()) {
                        $errors[] = $this->getError();
                        $return = false;
                    }
                } else {
                    $error[] = $this->getError();
                    $return = false;
                }

                if (!$return){
                    $this->setFiles();
                }
            }

            if ($return) {
                $fileNames = array();

                for ($i = 0; $i < count($name); $i++) {
                    if ($this->setFiles($name[$i], $tmp_name[$i], $size[$i], $error[$i])) {
                        $this->setNewFileName();
                        if (!$this->copyFile()) {
                            $errors = $this->getError();
                            $return = false;
                        } else {
                            $fileNames[] = $this->newFileName;
                        }
                    }
                }

                $this->newFileName = $fileNames;
            }

            $this->errorMess = $errors;
            return $return;
        } else {
            if ($this->setFiles($name, $tmp_name, $size, $error)) {
                if ($this->checkFileSize() && $this->checkFileType()) {
                    $this->setNewFileName();

                    if ($this->copyFile()) {
                        return true;
                    } else {
                        $return = false;
                    }
                } else {
                    $return = false;
                }
            } else {
                $return = false;
            }

            if (!$return)
                $this->errorMess = $this->getError();

            return $return;
        }
    }

    private function copyFile() {
        if (!$this->errorNum) {
            $filepath = rtrim($this->filepath, '/') . '/';
            $filepath.=$this->newFileName;

            if (@move_uploaded_file($this->tmpFileName, $filepath)) {
                return true;
            } else {
                $this->setOption('errorNum', -3);
                return false;
            }
        } else {
            return false;
        }
    }

//设置和$_FILES有关的内容
    private function setFiles($name = "", $tmp_name = '', $size = 0, $error = 0) {
        $this->setOption('errorNum', $error);
        if ($error) {
            return false;
        }

        $this->setOption('originName', $name);
        $this->setOption('tmpFileName', $tmp_name);
        $arrStr = explode('.', $name);
        $this->setOption('fileType', strtolower($arrStr[count($arrStr) - 1]));
        $this->setOption('fileSize', $size);

        return true;
    }

//用于获取上传后文件的文件名
    function getNewFileName() {
        return $this->newFileName;
    }

//上传如果失败，则调用这个方法，就可以查看错误报告
    function getErrorMsg() {
        return $this->errorMess;
    }

    /* 图片缩放函数
      $picname 被缩放后的处理图片源
      $maxx    被缩放后的最大宽度
      $maxy    被缩放后的最大高度
      $pre     被缩放后的图片名的前缀名
     */

    function imageupdatesize($picname, $maxx, $maxy, $pre) {
        $info = getimagesize($picname); //获取源图片的基本信息

        $w = $info[0]; //获取源图片的宽
        $h = $info[1]; //获取源图片的高
        //获取源图片的类型并为此创建对应的图片资源
        switch ($info[2]) {
            case 1: //gif
                $im = imagecreatefromgif($picname);
                break;
            case 2:  //jpg
                $im = imagecreatefromjpeg($picname);
                break;
            case 3:  //png
                $im = imagecreatefrompng($picname);
                break;
            default:
                die('图片类型错误');
        }

        //计算缩放比例
        if (($maxx / $w) > ($maxy / $h)) {
            $b = $maxy / $h;
        } else {
            $b = $maxx / $w;
        }

        //计算出缩放后的尺寸
        $nw = floor($w * $b);
        $nh = floor($h * $b);

        //创建一个新的图像源(缩放后的图片)
        $nim = imagecreatetruecolor($nw, $nh);

        //执行等比缩放
        imagecopyresampled($nim, $im, 0, 0, 0, 0, $nw, $nh, $w, $h);

        //输出图像(根据原图像的类型，输出为对应的类型)
        $picinfo = pathinfo($picname);  //解析源图像的名字和路径
        $newpicname = $picinfo["dirname"] . "/" . $pre . $picinfo["basename"];
        switch ($info[2]) {
            case 1:
                imagegif($nim, $newpicname);
                break;
            case 2:
                imagejpeg($nim, $newpicname);
                break;
            case 3:
                imagepng($nim, $newpicname);
                break;
        }

        //释放图片资源
        imagedestroy($im);
        imagedestroy($nim);

        //返回结果
        // return $newpicname;
    }

//建立目录函数
    function mkdirs($dir) {
        return is_dir($dir) or ( $this->mkdirs(dirname($dir)) and mkdir($dir, 0777));
    }

    /*
      根据比例来截取图片的最大面积
      $target_ratio 图片的宽高比例，例如1
      $file 图片的路径
     */

    function cropMaxArea($target_ratio, $file) {

        $imginfo = getimagesize($file);
        $width = $imginfo[0];
        $height = $imginfo[1];

        $oriRate = $width / $height;
//echo "{$target_ratio}:{$oriRate}";exit;
        if ($target_ratio < $oriRate) { //use height as the max
            $taget_h = $height;
            $taget_w = intval($height * $target_ratio);
            $start_x = intval(($width - $taget_w) / 2);
            $start_y = 0;
            $end_x = $start_x + $taget_w;
            $end_y = $taget_h;
        } else { //use width as the max
            $taget_w = $width;
            $taget_h = intval($width / $target_ratio);
            $start_x = 0;
            $start_y = intval(($height - $taget_h) / 2);
            $end_x = $taget_w;
            $end_y = $start_y + $taget_h;
        }
//echo "[{$start_x}]:{$start_y}:{$end_x}:{$end_y}:{$taget_w}:{$taget_h}";
//exit;
        $im = imagecreatetruecolor($taget_w, $taget_h);
        $thisim = @imagecreatefromjpeg($file);
        imagecopy($im, $thisim, 0, 0, $start_x, $start_y, $end_x, $end_y);
        imagejpeg($im, $file, 100);
        imagedestroy($im);
    }

}
